import {float32ToBytes, calculateResponseValue} from './dataUtil'


const Pattern = /ff55(.*?)0d0a/

let byte2Hex = (n:number)=>{
    let code = n.toString(16)
    let margin = 2-code.length
    if(margin != 0){
        code = '0'.repeat(margin) + code
    }
    return code
}

let short2Hex = (n:number)=>{
    let code = n.toString(16)
    let margin = 4-code.length
    if(margin != 0){
        code = '0'.repeat(margin) + code
    }
    return code
}

let long2Hex = (n:number)=>{
    let code = n.toString(16)
    let margin = 8-code.length
    if(margin != 0){
        code = '0'.repeat(margin) + code
    }
    return code
}

let byteArray2hexStr = (bytes:number[]) => {
    return bytes.map(b=>byte2Hex(b)).join('')
}

let hexStr2ByteArray = (hexStr:string) => {
    if(hexStr.length % 2 !== 0) throw `${hexStr} is not valid HEX`
    let r = []
    let byteLen = hexStr.length/2
    for(let i = 0; i<byteLen; i = i+1){
        let hexByte = hexStr.substr(i*2, 2)
        let num = parseInt(hexByte, 16)
        r.push(num)
    }
    return r
}

export class FF55Protocol implements IProtocolMiddleware {
    id : string
    // 无匹配项
    onMatchFallback : (hexStr : string) => void;

    constructor() {
        this.id = 'ff55'
    }
    // 从buffer中提取该协议
    extract(hex : string) : [string, number, number] {
        let r = hex.match(Pattern)
        if(!r) return null
        return [r[1], r.index, r[0].length]
    }

    // 打包该协议
    decorate(dataBody:string):string {
        return `ff55${dataBody}`
    }

    get typedef(){
        return {
            byte: {
                length: 1,
                pack(data : number): string {
                    return byte2Hex(data);
                },
                unpack(hex : string): number {
                    let n = parseInt(hex, 16)
                    return n
                }
            },
            BYTE: {
                length: 1,
                pack(data : number): string {
                    return byte2Hex(data);
                },
                unpack(hex : string): number {
                    let n = parseInt(hex, 16)
                    return n
                }
            },
            short: {
                length: 2,
                pack(data : number): string {
                    return short2Hex(data);
                },
                unpack(hex : string): number {
                    let n = parseInt(hex, 16)
                    return n
                }
            },
            SHORT: {
                length: 2,
                pack(data : number): string {
                    return short2Hex(data);
                },
                unpack(hex : string): number {
                    console.log('hex', hex)
                    let bs = hexStr2ByteArray(hex)
                    console.log('bs', bs)
                    bs.reverse()
                    console.log('bs1', bs)
                    let byteBuff = new Uint8Array(bs)
                    let n = calculateResponseValue(byteBuff)
                    return n
                }
            },
            float: {
                length: 4,
                pack(data : number): string {
                    return byteArray2hexStr(float32ToBytes(data));
                },
                unpack(hex : string): number {
                    console.log('hex', hex)
                    let bs = hexStr2ByteArray(hex)
                    console.log('bs', bs)
                    bs.reverse()
                    console.log('bs1', bs)
                    let byteBuff = new Uint8Array(bs)
                    let n = calculateResponseValue(byteBuff)
                    return n
                }
            },
            long: {
                length: 4,
                pack(data : number): string {
                    return long2Hex(data);
                },
                unpack(hex : string): number {
                    console.log('hex', hex)
                    let bs = hexStr2ByteArray(hex)
                    console.log('bs', bs)
                    bs.reverse()
                    console.log('bs1', bs)
                    let byteBuff = new Uint8Array(bs)
                    let n = calculateResponseValue(byteBuff)
                    return n
                }
            },
            string: {
                pack(data : string): string {
                    let r = ''
                    for(let d of data) {
                        let code = byte2Hex(d.charCodeAt(0))
                        r = r + code;
                    }
                    return byte2Hex(data.length)+ r
                },

                unpack(hex : string): string {
                    let r = ''
                    let slen = hex.substr(0,2);
                    let len = parseInt(slen)
                    let hexString = hex.substr(2, len*2);
                    for(let i = 0; i<hexString.length; i = i+2){
                        let charCode = parseInt(hexString[i]+hexString[i+1], 16)
                        let ch = String.fromCharCode(charCode)
                        r = r+ch
                    }
                    return r
                }
            }
        }
    } 
}
